home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / bbsckit / umodem.c < prev   
Text File  |  1979-12-31  |  45KB  |  1,414 lines

  1.  
  2. /*
  3.  *  UMODEM Version 3.7
  4.  *
  5.  *  UMODEM -- Implements the "CP/M User's Group XMODEM" protocol, 
  6.  *        the TERM II File Transfer Protocol (FTP) Number 1,
  7.  *        and the TERM II File Transfer Protocol Number 4 for
  8.  *        packetized file up/downloading.    
  9.  *
  10.  *    Note: UNIX System-Dependent values are indicated by the string [SD]
  11.  *      in a comment field on the same line as the values.
  12.  *
  13.  *
  14.  *     -- Lauren Weinstein, 6/81
  15.  *     -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
  16.  *     -- Version 2.1 Mods by Richard Conn, 8/2/81
  17.  *          . File Size Included on Send Option
  18.  *     -- Version 2.2 Mods by Richard Conn, 8/2/81
  19.  *          . Log File Generation and Option Incorporated
  20.  *     -- Version 2.3 Mods by Richard Conn, 8/3/81
  21.  *          . TERM II FTP 1 Supported
  22.  *          . Error Log Reports Enhanced
  23.  *     -- Version 2.4 Mods by Richard Conn, 8/4/81
  24.  *          . 16K-extent sector number check error corrected
  25.  *          . Count of number of received sectors added
  26.  *     -- Version 2.5 Mods by Richard Conn, 8/5/81
  27.  *          . ARPA Net Flag added
  28.  *          . ARPA Net parameter ('a') added to command line
  29.  *          . ARPA Net BIS, BIE, BOS, BOE added
  30.  *          . ARPA Net FFH escape added
  31.  *     -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
  32.  *          . mods for UNIX V7 (Note: for JHU compilation define
  33.  *        the variable JHU  during 'cc'
  34.  *          . added 'mungmode' flag to protect from inadvertant
  35.  *        overwrite on file receive
  36.  *          . changed timeout handling prior to issuing checksum
  37.  *     -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
  38.  *          . correct minor "ifndef" error in which ifndef had no arg
  39.  *          . restructured "ifdef" references so that other versions
  40.  *        of UNIX than Version 7 and JHU can be easily incorporated;
  41.  *        previous ifdef references were for JHU/not JHU;
  42.  *        to compile under Version 7 or JHU UNIX, the following
  43.  *        command lines are recommended:
  44.  *              "cc umodem.c -o umodem -DVER7" for Version 7
  45.  *              "cc -7 umodem.c -o umodem -DJHU" for JHU
  46.  *          . added 'y' file status display option; this option gives
  47.  *        the user an estimate of the size of the target file to
  48.  *        send from the UNIX system in terms of CP/M records (128
  49.  *        bytes) and Kbytes (1024 byte units)
  50.  *          . added '7' option which modifies the transmission protocols
  51.  *        for 7 significant bits rather than 8; modifies both FTP 1
  52.  *        and FTP 3
  53.  *     -- Version 2.8 Mods by Richard Conn, 8/28/81
  54.  *          . corrected system-dependent reference to TIOCSSCR (for
  55.  *        disabling page mode) and created the PAGEMODE flag which
  56.  *        is to be set to TRUE to enable this
  57.  *          . added -4 option which engages TERM II, FTP 4 (new release)
  58.  *     -- Version 2.9 Mods by Richard Conn, 9/1/81
  59.  *          . internal documentation on ARPA Net protocols expanded
  60.  *          . possible operator precedence problem with BITMASK corrected
  61.  *        by redundant parentheses
  62.  *     -- Version 3.0 Mods by Lauren Weinstein, 9/14/81
  63.  *          . fixed bug in PAGEMODE defines (removed PAGEMODE define
  64.  *        line; now should be compiled with "-DPAGEMODE" if
  65.  *        Page Mode is desired)
  66.  *          . included forward declaration of ttyname() to avoid problems
  67.  *        with newer V7 C compilers
  68.  *     -- Version 3.1 Mods by Lauren Weinstein, 4/17/82
  69.  *          . avoids sending extraneous last sector when file EOF
  70.  *        occurs on an exact sector boundary
  71.  *     -- Version 3.2 Mods by Michael M Rubenstein, 5/26/83
  72.  *          . fixed bug in readbyte.  assumed that int's are ordered
  73.  *        from low significance to high
  74.  *          . added LOGDEFAULT define to allow default logging to be
  75.  *        off.  compile with -DLOGDEFAULT=0 to set default to no
  76.  *        logging.
  77.  *     -- Version 3.3 Mod by Ben Goldfarb, 07/02/83
  78.  *          . Corrected problem with above implementation of "LOGDEFAULT".
  79.  *        A bitwise, instead of a logical negation operator was
  80.  *        used to complement LOGFLAG when the '-l' command line
  81.  *        flag was specified.  This can cause LOGFLAG to be true
  82.  *        when it should be false.
  83.  *     -- Version 3.4 Mods by David F. Hinnant, NCECS, 7/15/83
  84.  *          . placed log file in HOME directory in case user doesn't
  85.  *        have write permission in working directory.
  86.  *          . added DELDEFAULT define to allow default purge/no purge
  87.  *        of logfile before starting.  Compile with -DDELDEFAULT=0
  88.  *        to set default to NOT delete the log file before starting.
  89.  *          . check log file for sucessful fopen().
  90.  *          . buffer disk read for sfile().
  91.  *          . turn messages off (standard v7) before starting.
  92.  *     -- Version 3.5 Mods by Richard Conn, 08/27/83
  93.  *          . added equates for compilation under UNIX SYSTEM III
  94.  *              to compile for SYSTEM III, use -DSYS3 instead of
  95.  *              -DJHU or -DVER7
  96.  *          . added command mode (-c option) for continuous entry
  97.  *              of commands
  98.  *     -- Version 3.6 Mods by Ben Goldfarb (ucf-cs!goldfarb), 09/03/83
  99.  *          . added '#include <ctype.h>' since tolower() is used, but
  100.  *        is not defined in umodem.  This is necessary to compile
  101.  *        on V7 systems.  Also added a isupper() test because 
  102.  *        tolower() in /usr/include/ctype.h doesn't do that.
  103.  *          . cleaned up all the improper bitwise complementation of
  104.  *        logical constants and variables.
  105.  *     -- Version 3.7 Mods by Noel J. Bergman, 02/27/84
  106.  *          . Corrected problem with ALARM signal in 4.2 BSD Unix.
  107.  *        BSD Unix restarts system calls after signal is handled,
  108.  *        so setjmp() and longjmp() are used to handle I/O timeout.
  109.  *        Since this will work with all Unix systems, and is a lot
  110.  *        cleaner than depending on side effects, there is no need
  111.  *        to make this code conditional.
  112.  *
  113.  */
  114.  
  115. #include <stdio.h>
  116. #include <sys/types.h>
  117. #include <sys/stat.h>
  118. #include <setjmp.h>
  119. #include <ctype.h>
  120.  
  121. /*  JHU UNIX tty parameter file  */
  122. #ifdef JHU
  123. #include <stty.h>
  124. #endif
  125.  
  126. /*  Version 7 UNIX tty parameter file  */
  127. #ifdef VER7
  128. #include <sgtty.h>
  129. #endif
  130.  
  131. /*  UNIX SYSTEM III tty parameter file  */
  132. #ifdef SYS3
  133. #include <sgtty.h>
  134. #endif
  135.  
  136. /* log default define */
  137. #ifndef LOGDEFAULT
  138. #define LOGDEFAULT      1
  139. #endif
  140.  
  141. /* Delete logfile define.  Useful on small systems with limited
  142.  * filesystem space and careless users.
  143.  */
  144. #ifndef DELDEFAULT
  145. #define DELDEFAULT      1
  146. #endif
  147.  
  148. #include <signal.h>
  149.  
  150. #define      VERSION    37      /* Version Number */
  151. #define      FALSE      0
  152. #define      TRUE       1 
  153.  
  154. /*  Compile with "-DPAGEMODE" if Page Mode (TIOCSSCR) is supported on your
  155.  *  UNIX system.  If it is supported, make sure that TIOCSSCR is the
  156.  *  correct name for Page Mode engagement.
  157.  */
  158.  
  159. /*  ASCII Constants  */
  160. #define      SOH    001 
  161. #define      STX    002
  162. #define      ETX    003
  163. #define      EOT    004
  164. #define      ENQ    005
  165. #define      ACK    006
  166. #define      LF     012   /* Unix LF/NL */
  167. #define      CR     015  
  168. #define      NAK    025
  169. #define      SYN    026
  170. #define      CAN    030
  171. #define      ESC    033
  172. #define      CTRLZ      032   /* CP/M EOF for text (usually!) */
  173.  
  174. /*  UMODEM Constants  */
  175. #define      TIMEOUT    -1
  176. #define      ERRORMAX   10    /* maximum errors tolerated */
  177. #define      RETRYMAX   10    /* maximum retries to be made */
  178. #define      BBUFSIZ    128   /* buffer size -- do not change! */
  179.  
  180. /*  [SD] Mode for Created Files  */
  181. #define      CREATMODE  0600  /* mode for created files */
  182.  
  183. /*  ARPA Net Constants  */
  184. /*      The following constants are used to communicate with the ARPA
  185.  *      Net SERVER TELNET and TIP programs.  These constants are defined
  186.  *      as follows:
  187.  *          IAC             <-- Is A Command; indicates that
  188.  *                          a command follows
  189.  *          WILL/WONT           <-- Command issued to SERVER TELNET
  190.  *                          (Host); WILL issues command
  191.  *                          and WONT issues negative of
  192.  *                          the command
  193.  *          DO/DONT         <-- Command issued to TIP; DO issues
  194.  *                          command and DONT issues
  195.  *                          negative of the command
  196.  *          TRBIN           <-- Transmit Binary Command
  197.  *      Examples:
  198.  *          IAC WILL TRBIN  <-- Host is configured to transmit Binary
  199.  *          IAC WONT TRBIN  <-- Host is configured NOT to transmit binary
  200.  *          IAC DO TRBIN    <-- TIP is configured to transmit Binary
  201.  *          IAC DONT TRBIN  <-- TIP is configured NOT to transmit binary
  202.  */
  203. #define      IAC    0377    /* Is A Command */
  204. #define      DO     0375    /* Command to TIP */
  205. #define      DONT       0376    /* Negative of Command to TIP */
  206. #define      WILL       0373    /* Command to SERVER TELNET (Host) */
  207. #define      WONT       0374    /* Negative of Command to SERVER TELNET */
  208. #define      TRBIN      0       /* Transmit Binary Command */
  209.  
  210. /*  JHU UNIX structures  */
  211. #ifdef JHU
  212. struct sttybuf ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  213. #endif
  214.  
  215. /*  Version 7 UNIX structures  */
  216. #ifdef VER7
  217. struct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  218. #endif
  219.  
  220. /*  UNIX SYSTEM III structures  */
  221. #ifdef SYS3
  222. struct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  223. #endif
  224.  
  225. struct stat statbuf;    /* for terminal message on/off control */
  226. char *strcat();
  227. FILE *LOGFP, *fopen();
  228. char buff[BBUFSIZ];
  229. int nbchr;  /* number of chars read so far for buffered read */
  230.  
  231. int wason;
  232.  
  233. #ifdef VER7
  234. int pagelen;
  235. char *ttyname();  /* forward declaration for C */
  236. #endif
  237.  
  238. #ifdef SYS3
  239. int pagelen;
  240. char *ttyname();  /* forward declaration for C */
  241. #endif
  242.  
  243. char *tty;
  244. char XMITTYPE;
  245. int ARPA, CMNDFLAG, RECVFLAG, SENDFLAG, FTP1, PMSG, DELFLAG, LOGFLAG, MUNGMODE;
  246. int STATDISP, BIT7, BITMASK;
  247. int delay;
  248. char filename[256];
  249.  
  250. jmp_buf env;
  251. void alarmfunc();
  252.  
  253. main(argc, argv)
  254. int argc;
  255. char **argv;
  256. {
  257.     char *getenv();
  258.     char *fname = filename;
  259.     char *logfile;
  260.     int index;
  261.     char flag;
  262.  
  263.     logfile = "umodem.log";  /* Name of LOG File */
  264.  
  265.     printf("\nUMODEM Version %d.%d", VERSION/10, VERSION%10);
  266.     printf(" -- UNIX-Based Remote File Transfer Facility\n");
  267.  
  268.     if (argc < 2 || *argv[1] != '-')
  269.     {
  270.         help(FALSE);
  271.         exit(-1);
  272.     }
  273.  
  274.     index = 1;  /* set index for loop */
  275.     delay = 3;  /* assume FTP 3 delay */
  276.     PMSG = FALSE;  /* turn off flags */
  277.     FTP1 = FALSE;  /* assume FTP 3 (CP/M UG XMODEM2) */
  278.     RECVFLAG = FALSE;  /* not receive */
  279.     SENDFLAG = FALSE;  /* not send either */
  280.     CMNDFLAG = FALSE;  /* not command either */
  281.     XMITTYPE = 't';  /* assume text */
  282.     DELFLAG = DELDEFAULT;
  283.     LOGFLAG = LOGDEFAULT;
  284.     ARPA = FALSE;  /* assume not on ARPA Net */
  285.     MUNGMODE = FALSE; /* protect files from overwriting */
  286.     STATDISP = FALSE;  /* assume not a status display */
  287.     BIT7 = FALSE;  /* assume 8-bit communication */
  288.     while ((flag = argv[1][index++]) != '\0')
  289.         switch (flag) {
  290.         case '1' : FTP1 = TRUE;  /* select FTP 1 */
  291.                delay = 5;  /* FTP 1 delay constant */
  292.                printf("\nUMODEM:  TERM II FTP 1 Selected\n");
  293.                break;
  294.         case '4' : FTP1 = TRUE;  /* select FTP 1 (varient) */
  295.                BIT7 = TRUE;  /* transfer only 7 bits */
  296.                delay = 5;  /* FTP 1 delay constant */
  297.                printf("\nUMODEM:  TERM II FTP 4 Selected\n");
  298.                break;
  299.         case '7' : BIT7 = TRUE;  /* transfer only 7 bits */
  300.                break;
  301.         case 'a' : ARPA = TRUE;  /* set ARPA Net */
  302.                break;
  303.         case 'c' : CMNDFLAG = TRUE;  /* command mode */
  304.                break;
  305.         case 'd' : DELFLAG = !DELDEFAULT;  /* delete log file ? */
  306.                break;
  307.         case 'l' : LOGFLAG = !LOGDEFAULT;  /* turn off log ? */
  308.                break;
  309.         case 'm' : MUNGMODE = TRUE; /* allow overwriting of files */
  310.                break;
  311.         case 'p' : PMSG = TRUE;  /* print all messages */
  312.                break;
  313.         case 'r' : RECVFLAG = TRUE;  /* receive file */
  314.                XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
  315.                break;
  316.         case 's' : SENDFLAG = TRUE;  /* send file */
  317.                XMITTYPE = gettype(argv[1][index++]);
  318.                break;
  319.         case 'y' : STATDISP = TRUE;  /* display file status */
  320.                break;
  321.         default  : error("Invalid Flag", FALSE);
  322.         }
  323.  
  324.     if (BIT7 && (XMITTYPE == 'b'))
  325.     {  printf("\nUMODEM:  Fatal Error -- Both 7-Bit Transfer and ");
  326.        printf("Binary Transfer Selected");
  327.        exit(-1);  /* error exit to UNIX */
  328.     }
  329.  
  330.     if (BIT7)  /* set MASK value */
  331.        BITMASK = 0177;  /* 7 significant bits */
  332.     else
  333.        BITMASK = 0377;  /* 8 significant bits */
  334.  
  335.     if (PMSG)
  336.        { printf("\nSupported File Transfer Protocols:");
  337.          printf("\n\tTERM II FTP 1");
  338.          printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
  339.          printf("\n\tTERM II FTP 4");
  340.          printf("\n\n");
  341.        }
  342.  
  343.     if (CMNDFLAG) LOGFLAG = TRUE;  /* if command mode, always log */
  344.     if (LOGFLAG)
  345.        { 
  346.          if ((fname = getenv("HOME")) == 0) /* Get HOME variable */
  347.         error("Can't get Environment!", FALSE);
  348.          fname = strcat(fname, "/");
  349.          fname = strcat(fname, logfile);
  350.          if (!DELFLAG)
  351.         LOGFP = fopen(fname, "a");  /* append to LOG file */
  352.          else
  353.         LOGFP = fopen(fname, "w");  /* new LOG file */
  354.          if (!LOGFP)
  355.         error("Can't Open Log File", FALSE);
  356.          fprintf(LOGFP,"\n\n++++++++\n");
  357.          fprintf(LOGFP,"\nUMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  358.          printf("\nUMODEM:  LOG File '%s' is Open\n", fname);
  359.        }
  360.  
  361.     if (STATDISP) {
  362.         yfile(argv[2]);  /* status of a file */
  363.         exit(0);  /* exit to UNIX */
  364.         }
  365.  
  366.     if (RECVFLAG && SENDFLAG)
  367.         error("Both Send and Receive Functions Specified", FALSE);
  368.     if (!RECVFLAG && !SENDFLAG && !CMNDFLAG)
  369.         error("Send, Receive, or Command Functions NOT Given", FALSE);
  370.  
  371.     if (RECVFLAG)
  372.     {  if(open(argv[2], 0) != -1)  /* possible abort if file exists */
  373.        {    printf("\nUMODEM:  Warning -- Target File Exists\n");
  374.         if( MUNGMODE == FALSE )
  375.             error("Fatal - Can't overwrite file\n",FALSE);
  376.         printf("UMODEM:  Overwriting Target File\n");
  377.        }
  378.        rfile(argv[2]);  /* receive file */
  379.     }
  380.     else {
  381.         if (SENDFLAG) sfile(argv[2]);  /* send file */
  382.         else command();  /* command mode */
  383.         }
  384.     if (CMNDFLAG) LOGFLAG = TRUE;  /* for closing log file */
  385.     if (LOGFLAG) fclose(LOGFP);
  386.     exit(0);
  387. }
  388.  
  389. /*  Major Command Mode  */
  390. command()
  391. {
  392.     char cmd, *fname;
  393.     char *infile();
  394.  
  395.     printf("\nUMODEM Command Mode -- Type ? for Help");
  396.     do {
  397.        printf("\n");
  398.        printf(FTP1 ? "1" : "3");  /* FTP 1 or 3? */
  399.        printf(BIT7 ? "7" : " ");  /* BIT 7 or not? */
  400.        printf(ARPA ? "A" : " ");  /* ARPA Net or not? */
  401.        printf(LOGFLAG ? "L" : " ");  /* Log Entries or not? */
  402.        printf(MUNGMODE ? "M" : " ");  /* Mung Files or not? */
  403.        printf(" UMODEM> ");
  404.        scanf("%s", filename);
  405.        cmd = isupper(filename[0]) ? tolower(filename[0]) : filename[0];
  406.        switch (cmd) {
  407.         case '1' : FTP1 = TRUE;  /* select FTP 1 */
  408.                delay = 5;  /* FTP 1 delay constant */
  409.                printf("\nTERM FTP 1 Selected");
  410.                break;
  411.         case '3' : FTP1 = FALSE; /* select FTP 3 */
  412.                delay = 3;  /* FTP 3 delay constant */
  413.                printf("\nTERM FTP 3 Selected");
  414.                break;
  415.         case '7' : BIT7 = !BIT7;  /* toggle 7 bit transfer */
  416.                printf("\n7-Bit Transfer %s Selected",
  417.                 BIT7 ? "" : "NOT");
  418.                break;
  419.         case 'a' : ARPA = !ARPA;  /* toggle ARPA Net */
  420.                printf("\nDDN Interface %s Selected",
  421.                 ARPA ? "" : "NOT");
  422.                break;
  423.         case 'l' : LOGFLAG = !LOGFLAG;  /* toggle log flag */
  424.                printf("\nEntry Logging %s Enabled",
  425.                 LOGFLAG ? "" : "NOT");
  426.                break;
  427.         case 'm' : MUNGMODE = !MUNGMODE; /* toggle file overwrite */
  428.                printf("\nFile Overwriting %s Enabled",
  429.                 MUNGMODE ? "" : "NOT");
  430.                break;
  431.         case 'r' : RECVFLAG = TRUE;  /* receive file */
  432.                XMITTYPE = tolower(filename[1]);
  433.                fname = infile();  /* get file name */
  434.                if (*fname != '\0') rfile(fname);
  435.                break;
  436.         case 's' : SENDFLAG = TRUE;  /* send file */
  437.                XMITTYPE = tolower(filename[1]);
  438.                fname = infile();  /* get file name */
  439.                if (*fname != '\0') sfile(fname);
  440.                break;
  441.         case 'x' : break;
  442.         case 'y' : fname = infile();  /* get file name */
  443.                if (*fname != '\0') yfile(fname);
  444.                break;
  445.         default  : help(TRUE);
  446.        }
  447.     } while (cmd != 'x');
  448. }
  449.  
  450. /*  Get file name from user  */
  451. char *infile()
  452. {
  453.     char *startptr = filename;
  454.  
  455.     scanf("%s",startptr);
  456.     if (*startptr == '.') *startptr = '\0';  /* set NULL */
  457.     return(startptr);
  458. }
  459.  
  460. /*  Print Help Message  */
  461. help(caller)
  462. int caller;
  463. {
  464.     if (!caller) { printf("\nUsage:  \n\tumodem ");
  465.         printf("-[c!rb!rt!sb!st][options]");
  466.         printf(" filename\n");
  467.         }
  468.     else {
  469.         printf("\nUsage: r or s or option");
  470.         }
  471.     printf("\nMajor Commands --");
  472.     if (!caller) printf("\n\tc  <-- Enter Command Mode");
  473.     printf("\n\trb <-- Receive Binary");
  474.     printf("\n\trt <-- Receive Text");
  475.     printf("\n\tsb <-- Send Binary");
  476.     printf("\n\tst <-- Send Text");
  477.     printf("\nOptions --");
  478.     printf("\n\t1  <-- (one) Employ TERM II FTP 1");
  479.     if (caller) printf("\n\t3  <-- Enable TERM FTP 3 (CP/M UG)");
  480.     if (!caller) printf("\n\t4  <-- Enable TERM FTP 4");
  481.     printf("\n\t7  <-- Enable 7-bit transfer mask");
  482.     printf("\n\ta  <-- Turn ON ARPA Net Flag");
  483.     if (!caller)
  484. #if DELDEFAULT == 1
  485.     printf("\n\td  <-- Do not delete umodem.log file before starting");
  486. #else
  487.     printf("\n\td  <-- Delete umodem.log file before starting");
  488. #endif
  489.  
  490.     if (!caller)
  491. #if LOGDEFAULT == 1
  492.     printf("\n\tl  <-- (ell) Turn OFF LOG File Entries");
  493. #else
  494.     printf("\n\tl  <-- (ell) Turn ON LOG File Entries");
  495. #endif
  496.     else printf("\n\tl  <-- Toggle LOG File Entries");
  497.  
  498.     printf("\n\tm  <-- Allow file overwiting on receive");
  499.     if (!caller) printf("\n\tp  <-- Turn ON Parameter Display");
  500.     if (caller) printf("\n\tx  <-- Exit");
  501.     printf("\n\ty  <-- Display file status (size) information only");
  502.     printf("\n");
  503. }
  504.  
  505. gettype(ichar)
  506. char ichar;
  507. {
  508.     if (ichar == 't') return(ichar);
  509.     if (ichar == 'b') return(ichar);
  510.     error("Invalid Send/Receive Parameter - not t or b", FALSE);
  511.     return;
  512. }
  513.  
  514. /* set tty modes for UMODEM transfers */
  515. setmodes()
  516. {
  517.  
  518. /*  Device characteristics for JHU UNIX  */
  519. #ifdef JHU      
  520.     if (gtty(0, &ttys) < 0)  /* get current tty params */
  521.         error("Can't get TTY Parameters", TRUE);
  522.  
  523.     tty = ttyname(0);  /* identify current tty */
  524.  
  525.     /* duplicate current modes in ttysnew structure */
  526.     ttysnew.ispeed = ttys.ispeed;   /* copy input speed */
  527.     ttysnew.ospeed = ttys.ospeed;   /* copy output speed */
  528.     ttysnew.xflags = ttys.xflags;   /* copy JHU/UNIX extended flags */
  529.     ttysnew.mode   = ttys.mode;     /* copy standard terminal flags */
  530.  
  531.     ttysnew.mode |= RAW;    /* set for RAW Mode */
  532.             /* This ORs in the RAW mode value, thereby
  533.                setting RAW mode and leaving the other
  534.                mode settings unchanged */
  535.     ttysnew.mode &= ~ECHO;  /* set for no echoing */
  536.             /* This ANDs in the complement of the ECHO
  537.                setting (for NO echo), thereby leaving all
  538.                current parameters unchanged and turning
  539.                OFF ECHO only */
  540.     ttysnew.mode &= ~XTABS;  /* set for no tab expansion */
  541.     ttysnew.mode &= ~LCASE;  /* set for no upper-to-lower case xlate */
  542.     ttysnew.mode |= ANYP;  /* set for ANY Parity */
  543.     ttysnew.mode &= ~NL3;  /* turn off ALL delays - new line */
  544.     ttysnew.mode &= ~TAB3; /* turn off tab delays */
  545.     ttysnew.mode &= ~CR3;  /* turn off CR delays */
  546.     ttysnew.mode &= ~FF1;  /* turn off FF delays */
  547.     ttysnew.mode &= ~BS1;  /* turn off BS delays */
  548.     /* the following are JHU/UNIX xflags settings; they are [SD] */
  549.     ttysnew.xflags &= ~PAGE;  /* turn off paging */
  550.     ttysnew.xflags &= ~STALL;  /* turn off ^S/^Q recognition */
  551.     ttysnew.xflags &= ~TAPE;  /* turn off ^S/^Q input control */
  552.     ttysnew.xflags &= ~FOLD;  /* turn off CR/LF folding at col 72 */
  553.     ttysnew.xflags |= NB8;  /* turn on 8-bit input/output */
  554.  
  555.     if (stty(0, &ttysnew) < 0)  /* set new params */
  556.         error("Can't set new TTY Parameters", TRUE);
  557.  
  558.     if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  559.         error("Can't get your TTY Status", TRUE);
  560.  
  561.     if (statbuf.st_mode&011)  /* messages are on [SD] */
  562.     {       wason = TRUE;
  563.         if (chmod(tty, 020600) < 0)  /* turn off tty messages [SD] */
  564.             error("Can't change TTY Mode", TRUE);
  565.     }       
  566.     else
  567.         wason = FALSE;  /* messages are already off */
  568. #endif      
  569.  
  570. /*  Device characteristics for Version 7 UNIX  */
  571. #ifdef VER7
  572.     if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  573.         error("Can't get TTY Parameters", TRUE);
  574.     tty = ttyname(0);  /* identify current tty */
  575.     
  576.     /* transfer current modes to new structure */
  577.     ttysnew.sg_ispeed = ttys.sg_ispeed;     /* copy input speed */
  578.     ttysnew.sg_ospeed = ttys.sg_ospeed;     /* copy output speed */
  579.     ttysnew.sg_erase  = ttys.sg_erase;      /* copy erase flags */
  580.     ttysnew.sg_flags  = ttys.sg_flags;      /* copy flags */
  581.     ttysnew.sg_kill   = ttys.sg_kill;       /* copy std terminal flags */
  582.     
  583.  
  584.     ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  585.             /* This ORs in the RAW mode value, thereby
  586.                setting RAW mode and leaving the other
  587.                mode settings unchanged */
  588.     ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
  589.             /* This ANDs in the complement of the ECHO
  590.                setting (for NO echo), thereby leaving all
  591.                current parameters unchanged and turning
  592.                OFF ECHO only */
  593.     ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
  594.     ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
  595.     ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
  596.     ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
  597.     ttysnew.sg_flags &= ~TAB2; /* turn off tab delays */
  598.     ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
  599.     ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
  600.     ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
  601.     ttysnew.sg_flags &= ~TANDEM;  /* turn off flow control */
  602.  
  603. #ifdef PAGEMODE
  604.     /* make sure page mode is off */
  605.     ioctl(0,TIOCSSCR,&pagelen);     /*  [SD]  */
  606. #endif
  607.     
  608.     /* set new paramters */
  609.     if (ioctl(0,TIOCSETP,&ttysnew) < 0)
  610.         error("Can't set new TTY Parameters", TRUE);
  611.  
  612.     if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  613.         error("Can't get your TTY Status", TRUE);
  614.     if (statbuf.st_mode & 022)      /* Need to turn messages off */
  615.         if (chmod(tty, statbuf.st_mode & ~022) < 0)
  616.             error("Can't change  TTY mode", TRUE);
  617.         else wason = TRUE;
  618.     else wason = FALSE;
  619. #endif  
  620.  
  621. /*  Device Characteristics for UNIX SYSTEM III  */
  622. #ifdef SYS3
  623.     if (gtty(0, &ttys) < 0)  /* get current tty params */
  624.         error("Can't get TTY Parameters", TRUE);
  625.  
  626.     tty = ttyname(0);  /* identify current tty */
  627.     
  628.     /* transfer current modes to new structure */
  629.     ttysnew.sg_ispeed = ttys.sg_ispeed;     /* copy input speed */
  630.     ttysnew.sg_ospeed = ttys.sg_ospeed;     /* copy output speed */
  631.     ttysnew.sg_erase  = ttys.sg_erase;      /* copy erase flags */
  632.     ttysnew.sg_flags  = ttys.sg_flags;      /* copy flags */
  633.     ttysnew.sg_kill   = ttys.sg_kill;       /* copy std terminal flags */
  634.     
  635.  
  636.     ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  637.             /* This ORs in the RAW mode value, thereby
  638.                setting RAW mode and leaving the other
  639.                mode settings unchanged */
  640.     ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
  641.             /* This ANDs in the complement of the ECHO
  642.                setting (for NO echo), thereby leaving all
  643.                current parameters unchanged and turning
  644.                OFF ECHO only */
  645.     ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
  646.     ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
  647.     ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
  648.     ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
  649.     ttysnew.sg_flags &= ~TAB0; /* turn off tab delays */
  650.     ttysnew.sg_flags &= ~TAB1;
  651.     ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
  652.     ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
  653.     ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
  654.  
  655.     if (stty(0, &ttysnew) < 0)  /* set new params */
  656.         error("Can't set new TTY Parameters", TRUE);
  657.  
  658.     if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  659.         error("Can't get your TTY Status", TRUE);
  660.     if (statbuf.st_mode & 022)      /* Need to turn messages off */
  661.         if (chmod(tty, statbuf.st_mode & ~022) < 0)
  662.             error("Can't change  TTY mode", TRUE);
  663.         else wason = TRUE;
  664.     else wason = FALSE;
  665. #endif
  666.  
  667.     if (PMSG)
  668.         { printf("\nUMODEM:  TTY Device Parameters Altered");
  669.           ttyparams();  /* print tty params */
  670.         }
  671.  
  672.     if (ARPA)  /* set 8-bit on ARPA Net */
  673.         setarpa();
  674.  
  675.     return;
  676. }
  677.  
  678. /*  set ARPA Net for 8-bit transfers  */
  679. setarpa()
  680. {
  681.     sendbyte(IAC);  /* Is A Command */
  682.     sendbyte(WILL); /* Command to SERVER TELNET (Host) */
  683.     sendbyte(TRBIN);    /* Command is:  Transmit Binary */
  684.  
  685.     sendbyte(IAC);  /* Is A Command */
  686.     sendbyte(DO);   /* Command to TIP */
  687.     sendbyte(TRBIN);    /* Command is:  Transmit Binary */
  688.  
  689.     sleep(3);  /* wait for TIP to configure */
  690.  
  691.     return;
  692. }
  693.  
  694. /* restore normal tty modes */
  695. restoremodes(errcall)
  696. int errcall;
  697. {
  698.     if (ARPA)  /* if ARPA Net, reconfigure */
  699.         resetarpa();
  700.  
  701. /*  Device characteristic restoration for JHU UNIX  */
  702. #ifdef JHU
  703.     if (wason)  /* if messages were on originally */
  704.         if (chmod(tty, 020611) < 0)  /*  [SD]  */
  705.             error("Can't change TTY Mode", FALSE);
  706.  
  707.     if (stty(0, &ttys) < 0)  /* restore original tty modes */
  708.         { if (!errcall)
  709.            error("RESET - Can't restore normal TTY Params", FALSE);
  710.         else
  711.            { printf("UMODEM:  ");
  712.              printf("RESET - Can't restore normal TTY Params\n");
  713.            }
  714.         }
  715. #endif
  716.  
  717. /*  Device characteristic restoration for Version 7 UNIX  */
  718. #ifdef VER7
  719.     if (wason)
  720.         if (chmod(tty, statbuf.st_mode | 022) < 0)
  721.             error("Can't change TTY mode", FALSE);
  722.     if (ioctl(0,TIOCSETP,&ttys) < 0)
  723.         { if (!errcall)
  724.            error("RESET - Can't restore normal TTY Params", FALSE);
  725.         else
  726.            { printf("UMODEM:  ");
  727.              printf("RESET - Can't restore normal TTY Params\n");
  728.            }
  729.         }
  730. #endif
  731.  
  732. /*  Device characteristic restoration for UNIX SYSTEM III  */
  733. #ifdef SYS3
  734.     if (wason)
  735.         if (chmod(tty, statbuf.st_mode | 022) < 0)
  736.             error("Can't change TTY mode", FALSE);
  737.  
  738.     if (stty(0, &ttys) < 0)  /* restore original tty modes */
  739.         { if (!errcall)
  740.            error("RESET - Can't restore normal TTY Params", FALSE);
  741.         else
  742.            { printf("UMODEM:  ");
  743.              printf("RESET - Can't restore normal TTY Params\n");
  744.            }
  745.         }
  746. #endif
  747.  
  748.     if (PMSG)
  749.         { printf("\nUMODEM:  TTY Device Parameters Restored");
  750.           ttyparams();  /* print tty params */
  751.         }
  752.  
  753.     return;
  754. }
  755.  
  756. /* reset the ARPA Net */
  757. resetarpa()
  758. {
  759.     sendbyte(IAC);  /* Is A Command */
  760.     sendbyte(WONT); /* Negative Command to SERVER TELNET (Host) */
  761.     sendbyte(TRBIN);    /* Command is:  Don't Transmit Binary */
  762.  
  763.     sendbyte(IAC);  /* Is A Command */
  764.     sendbyte(DONT); /* Negative Command to TIP */
  765.     sendbyte(TRBIN);    /* Command is:  Don't Transmit Binary */
  766.  
  767.     return;
  768. }
  769.  
  770. /* print error message and exit; if mode == TRUE, restore normal tty modes */
  771. error(msg, mode)
  772. char *msg;
  773. int mode;
  774. {
  775.     if (mode)
  776.         restoremodes(TRUE);  /* put back normal tty modes */
  777.     printf("UMODEM:  %s\n", msg);
  778.     if (LOGFLAG & (int)LOGFP)
  779.     {   fprintf(LOGFP, "UMODEM Fatal Error:  %s\n", msg);
  780.         fclose(LOGFP);
  781.     }
  782.     exit(-1);
  783. }
  784.  
  785. /**  print status (size) of a file  **/
  786. yfile(name)
  787. char *name;
  788. {
  789.     printf("\nUMODEM File Status Display for %s\n", name);
  790.  
  791.     if (open(name,0) < 0) {
  792.         printf("File %s does not exist\n", name);
  793.         return;
  794.         }
  795.  
  796.     prfilestat(name);  /* print status */
  797.     printf("\n");
  798. }
  799.  
  800. getbyte(fildes, ch)                 /* Buffered disk read */
  801. int fildes;
  802. char *ch;
  803. /*
  804.  *
  805.  *      Get a byte from the specified file.  Buffer the read so we don't
  806.  *      have to use a system call for each character.
  807.  *
  808.  */
  809.  
  810. {
  811.     static char buf[BUFSIZ];    /* Remember buffer */
  812.     static char *bufp = buf;    /* Remember where we are in buffer */
  813.     
  814.     if (nbchr == 0)         /* Buffer exausted; read some more */
  815.     {
  816.         if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  817.             error("File Read Error", TRUE);
  818.         bufp = buf;         /* Set pointer to start of array */
  819.     }
  820.     if (--nbchr >= 0)
  821.     {
  822.         *ch = *bufp++;
  823.         return(0);
  824.     }
  825.     else
  826.         return(EOF);
  827. }
  828.  
  829. /**  receive a file  **/
  830. rfile(name)
  831. char *name;
  832. {
  833.     char mode;
  834.     int fd, j, firstchar, sectnum, sectcurr, tmode;
  835.     int sectcomp, errors, errorflag, recfin;
  836.     register int bufctr, checksum;
  837.     register int c;
  838.     int errorchar, fatalerror, startstx, inchecksum, endetx, endenq;
  839.     long recvsectcnt;
  840.  
  841.     mode = XMITTYPE;  /* set t/b mode */
  842.     if ((fd = creat(name, CREATMODE)) < 0)
  843.         error("Can't create file for receive", FALSE);
  844.     setmodes();  /* setup tty modes for xfer */
  845.     printf("\r\nUMODEM:  File Name: %s", name);
  846.     if (LOGFLAG)
  847.     {    fprintf(LOGFP, "\n----\nUMODEM Receive Function\n");
  848.          fprintf(LOGFP, "File Name: %s\n", name);
  849.          if (FTP1)
  850.         if (!BIT7)
  851.          fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  852.         else
  853.          fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  854.          else
  855.         fprintf(LOGFP,
  856.           "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  857.          if (BIT7)
  858.         fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  859.          else
  860.         fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  861.     }
  862.     printf("\r\nUMODEM:  ");
  863.     if (BIT7)
  864.         printf("7-Bit");
  865.     else
  866.         printf("8-Bit");
  867.     printf(" Transmission Enabled");
  868.     printf("\r\nUMODEM:  Ready to RECEIVE File\r\n");
  869.  
  870.     recfin = FALSE;
  871.     sectnum = errors = 0;
  872.     fatalerror = FALSE;  /* NO fatal errors */
  873.     recvsectcnt = 0;  /* number of received sectors */
  874.  
  875.     if (mode == 't')
  876.         tmode = TRUE;
  877.     else
  878.         tmode = FALSE;
  879.  
  880.     if (FTP1)
  881.     {
  882.       while (readbyte(4) != SYN);
  883.       sendbyte(ACK);  /* FTP 1 Sync */
  884.     }
  885.     else sendbyte(NAK);  /* FTP 3 Sync */
  886.  
  887.     do
  888.     {   errorflag = FALSE;
  889.         do {
  890.           firstchar = readbyte(6);
  891.         } while ((firstchar != SOH) && (firstchar != EOT) && (firstchar 
  892.              != TIMEOUT));
  893.         if (firstchar == TIMEOUT)
  894.         {  if (LOGFLAG)
  895.         fprintf(LOGFP, "Timeout on Sector %d\n", sectnum);
  896.            errorflag = TRUE;
  897.         }
  898.  
  899.         if (firstchar == SOH)
  900.         {  if (FTP1) readbyte(5);  /* discard leading zero */
  901.            sectcurr = readbyte(delay);
  902.            sectcomp = readbyte(delay);
  903.            if (FTP1) startstx = readbyte(delay);  /* get leading STX */
  904.            if ((sectcurr + sectcomp) == BITMASK)
  905.            {  if (sectcurr == ((sectnum+1)&BITMASK))
  906.           {  checksum = 0;
  907.              for (j = bufctr = 0; j < BBUFSIZ; j++)
  908.              {  buff[bufctr] = c = readbyte(delay);
  909.             checksum = ((checksum+c)&BITMASK);
  910.             if (!tmode)  /* binary mode */
  911.             {  bufctr++;
  912.                continue;
  913.             }
  914.             if (c == CR)
  915.                continue;  /* skip CR's */
  916.             if (c == CTRLZ)  /* skip CP/M EOF char */
  917.             {  recfin = TRUE;  /* flag EOF */
  918.                continue;
  919.             }
  920.             if (!recfin)
  921.                bufctr++;
  922.              }
  923.              if (FTP1) endetx = readbyte(delay);  /* get ending ETX */
  924.              inchecksum = readbyte(delay);  /* get checksum */
  925.              if (FTP1) endenq = readbyte(delay); /* get ENQ */
  926.              if (checksum == inchecksum)  /* good checksum */
  927.              {  errors = 0;
  928.             recvsectcnt++;
  929.             sectnum = sectcurr;  /* update sector counter */
  930.             if (write(fd, buff, bufctr) < 0)
  931.                error("File Write Error", TRUE);
  932.             else
  933.             {  if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  934.                sendbyte(ACK);
  935.             }
  936.              }
  937.              else
  938.              {  if (LOGFLAG)
  939.                 fprintf(LOGFP, "Checksum Error on Sector %d\n",
  940.                 sectnum);
  941.             errorflag = TRUE;
  942.              }
  943.           }
  944.           else
  945.           { if (sectcurr == sectnum)
  946.             {  while(readbyte(3) != TIMEOUT);
  947.                if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  948.                sendbyte(ACK);
  949.             }
  950.             else
  951.             {  if (LOGFLAG)
  952.             { fprintf(LOGFP, "Phase Error - Received Sector is ");
  953.               fprintf(LOGFP, "%d while Expected Sector is %d\n",
  954.                sectcurr, ((sectnum+1)&BITMASK));
  955.             }
  956.             errorflag = TRUE;
  957.             fatalerror = TRUE;
  958.             if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  959.             sendbyte(CAN);
  960.             }
  961.           }
  962.        }
  963.        else
  964.        {  if (LOGFLAG)
  965.         fprintf(LOGFP, "Header Sector Number Error on Sector %d\n",
  966.            sectnum);
  967.            errorflag = TRUE;
  968.        }
  969.     }
  970.     if (FTP1 && !errorflag)
  971.     {  if (startstx != STX)
  972.        {  errorflag = TRUE;  /* FTP 1 STX missing */
  973.           errorchar = STX;
  974.        }
  975.        if (endetx != ETX)
  976.        {  errorflag = TRUE;  /* FTP 1 ETX missing */
  977.           errorchar = ETX;
  978.        }
  979.        if (endenq != ENQ)
  980.        {  errorflag = TRUE;  /* FTP 1 ENQ missing */
  981.           errorchar = ENQ;
  982.        }
  983.        if (errorflag && LOGFLAG)
  984.        {  fprintf(LOGFP, "Invalid Packet-Control Character:  ");
  985.           switch (errorchar) {
  986.         case STX : fprintf(LOGFP, "STX"); break;
  987.         case ETX : fprintf(LOGFP, "ETX"); break;
  988.         case ENQ : fprintf(LOGFP, "ENQ"); break;
  989.         default  : fprintf(LOGFP, "Error"); break;
  990.           }
  991.           fprintf(LOGFP, "\n");
  992.        }
  993.     }
  994.     if (errorflag == TRUE)
  995.     {  errors++;
  996.        while (readbyte(3) != TIMEOUT);
  997.        sendbyte(NAK);
  998.     }
  999.   }
  1000.   while ((firstchar != EOT) && (errors != ERRORMAX) && !fatalerror);
  1001.   if ((firstchar == EOT) && (errors < ERRORMAX))
  1002.   {  if (!FTP1) sendbyte(ACK);
  1003.      close(fd);
  1004.      restoremodes(FALSE);  /* restore normal tty modes */
  1005.      if (FTP1)
  1006.     while (readbyte(3) != TIMEOUT);  /* flush EOT's */
  1007.      sleep(3);  /* give other side time to return to terminal mode */
  1008.      if (LOGFLAG)
  1009.      {  fprintf(LOGFP, "\nReceive Complete\n");
  1010.     fprintf(LOGFP,"Number of Received CP/M Records is %ld\n", recvsectcnt);
  1011.      }
  1012.      printf("\n");
  1013.   }
  1014.   else
  1015.   {  if (LOGFLAG && FTP1 && fatalerror) fprintf(LOGFP,
  1016.     "Synchronization Error");
  1017.      error("TIMEOUT -- Too Many Errors", TRUE);
  1018.   }
  1019. }
  1020.  
  1021. /**  send a file  **/
  1022. sfile(name)
  1023. char *name;
  1024. {
  1025.     char mode;
  1026.     int fd, attempts;
  1027.     int nlflag, sendfin, tmode;
  1028.     register int bufctr, checksum, sectnum;
  1029.     char c;
  1030.     int sendresp;  /* response char to sent block */
  1031.  
  1032.     nbchr = 0;  /* clear buffered read char count */
  1033.     mode = XMITTYPE;  /* set t/b mode */
  1034.     if ((fd = open(name, 0)) < 0)
  1035.     {  if (LOGFLAG) fprintf(LOGFP, "Can't Open File\n");
  1036.        error("Can't open file for send", FALSE);
  1037.     }
  1038.     setmodes();  /* setup tty modes for xfer */     
  1039.     printf("\r\nUMODEM:  File Name: %s", name);
  1040.     if (LOGFLAG)
  1041.     {   fprintf(LOGFP, "\n----\nUMODEM Send Function\n");
  1042.         fprintf(LOGFP, "File Name: %s\n", name);
  1043.     }
  1044.     printf("\r\n"); prfilestat(name);  /* print file size statistics */
  1045.     if (LOGFLAG)
  1046.     {  if (FTP1)
  1047.           if (!BIT7)
  1048.         fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  1049.           else
  1050.         fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  1051.        else
  1052.         fprintf(LOGFP,
  1053.            "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  1054.        if (BIT7)
  1055.         fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  1056.        else
  1057.         fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  1058.     }
  1059.     printf("\r\nUMODEM:  ");
  1060.     if (BIT7)
  1061.         printf("7-Bit");
  1062.     else
  1063.         printf("8-Bit");
  1064.     printf(" Transmission Enabled");
  1065.     printf("\r\nUMODEM:  Ready to SEND File\r\n");
  1066.  
  1067.     if (mode == 't')
  1068.        tmode = TRUE;
  1069.     else
  1070.        tmode = FALSE;
  1071.  
  1072.     sendfin = nlflag = FALSE;
  1073.     attempts = 0;
  1074.  
  1075.     if (FTP1)
  1076.     {  sendbyte(SYN);  /* FTP 1 Synchronize with Receiver */
  1077.        while (readbyte(5) != ACK)
  1078.        {  if(++attempts > RETRYMAX*6) error("Remote System Not Responding",
  1079.         TRUE);
  1080.           sendbyte(SYN);
  1081.        }
  1082.     }
  1083.     else
  1084.     {  while (readbyte(30) != NAK)  /* FTP 3 Synchronize with Receiver */
  1085.        if (++attempts > RETRYMAX) error("Remote System Not Responding",
  1086.         TRUE);
  1087.     }
  1088.  
  1089.     sectnum = 1;  /* first sector number */
  1090.     attempts = 0;
  1091.  
  1092.     do 
  1093.     {   for (bufctr=0; bufctr < BBUFSIZ;)
  1094.         {   if (nlflag)
  1095.         {  buff[bufctr++] = LF;  /* leftover newline */
  1096.            nlflag = FALSE;
  1097.         }
  1098.         if (getbyte(fd, &c) == EOF)
  1099.         {  sendfin = TRUE;  /* this is the last sector */
  1100.            if (!bufctr)  /* if EOF on sector boundary */
  1101.               break;  /* avoid sending extra sector */
  1102.            if (tmode)
  1103.               buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
  1104.            else
  1105.               bufctr++;
  1106.            continue;
  1107.         }
  1108.         if (tmode && c == LF)  /* text mode & Unix newline? */
  1109.         {  if (c == LF)  /* Unix newline? */
  1110.            {  buff[bufctr++] = CR;  /* insert carriage return */
  1111.               if (bufctr < BBUFSIZ)
  1112.              buff[bufctr++] = LF;  /* insert Unix newline */
  1113.               else
  1114.              nlflag = TRUE;  /* insert newline on next sector */
  1115.            }
  1116.            continue;
  1117.         }       
  1118.         buff[bufctr++]= c;  /* copy the char without change */
  1119.         }
  1120.         attempts = 0;
  1121.     
  1122.         if (!bufctr)  /* if EOF on sector boundary */
  1123.            break;  /* avoid sending empty sector */
  1124.  
  1125.         do
  1126.         {   sendbyte(SOH);  /* send start of packet header */
  1127.         if (FTP1) sendbyte(0);  /* FTP 1 Type 0 Packet */
  1128.         sendbyte(sectnum);  /* send current sector number */
  1129.         sendbyte(-sectnum-1);  /* and its complement */
  1130.         if (FTP1) sendbyte(STX);  /* send STX */
  1131.         checksum = 0;  /* init checksum */
  1132.         for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
  1133.         {  sendbyte(buff[bufctr]);  /* send the byte */
  1134.            if (ARPA && (buff[bufctr]==0xff))  /* ARPA Net FFH esc */
  1135.             sendbyte(buff[bufctr]);  /* send 2 FFH's for one */
  1136.            checksum = ((checksum+buff[bufctr])&BITMASK);
  1137.         }
  1138. /*          while (readbyte(3) != TIMEOUT);   flush chars from line */
  1139.         if (FTP1) sendbyte(ETX);  /* send ETX */
  1140.         sendbyte(checksum);  /* send the checksum */
  1141.         if (FTP1) sendbyte(ENQ);  /* send ENQ */
  1142.         attempts++;
  1143.         if (FTP1)
  1144.         {  sendresp = NAK;  /* prepare for NAK */
  1145.            if (readbyte(10) == ESC) sendresp = readbyte(10);
  1146.         }
  1147.         else
  1148.            sendresp = readbyte(10);  /* get response */
  1149.         if ((sendresp != ACK) && LOGFLAG)
  1150.            { fprintf(LOGFP, "Non-ACK Received on Sector %d\n",
  1151.               sectnum);
  1152.              if (sendresp == TIMEOUT)
  1153.             fprintf(LOGFP, "This Non-ACK was a TIMEOUT\n");
  1154.            }
  1155.         }   while((sendresp != ACK) && (attempts != RETRYMAX));
  1156.         sectnum++;  /* increment to next sector number */
  1157.     }  while (!sendfin && (attempts != RETRYMAX));
  1158.  
  1159.     if (attempts == RETRYMAX)
  1160.     error("Remote System Not Responding", TRUE);
  1161.  
  1162.     attempts = 0;
  1163.     if (FTP1)
  1164.     while (attempts++ < 10) sendbyte(EOT);
  1165.     else
  1166.     {   sendbyte(EOT);  /* send 1st EOT */
  1167.     while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
  1168.        sendbyte(EOT);
  1169.     if (attempts >= RETRYMAX)
  1170.        error("Remote System Not Responding on Completion", TRUE);
  1171.     }
  1172.  
  1173.     close(fd);
  1174.     restoremodes(FALSE);  
  1175.     sleep(5);  /* give other side time to return to terminal mode */
  1176.     if (LOGFLAG)
  1177.     {  fprintf(LOGFP, "\nSend Complete\n");
  1178.     }
  1179.     printf("\n");
  1180.  
  1181. }
  1182.  
  1183. /*  print file size status information  */
  1184. prfilestat(name)
  1185. char *name;
  1186. {
  1187.     struct stat filestatbuf; /* file status info */
  1188.  
  1189.     stat(name, &filestatbuf);  /* get file status bytes */
  1190.     printf("  Estimated File Size %ldK, %ld Records, %ld Bytes",
  1191.       (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  1192.       filestatbuf.st_size);
  1193.     if (LOGFLAG)
  1194.       fprintf(LOGFP,"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
  1195.       (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  1196.       filestatbuf.st_size);
  1197.     return;
  1198. }
  1199.  
  1200. /* get a byte from data stream -- timeout if "seconds" elapses */
  1201. readbyte(seconds)
  1202. unsigned seconds;
  1203. {
  1204.     char c;
  1205.     
  1206.     signal(SIGALRM,alarmfunc);  /* catch alarms */  
  1207.     alarm((unsigned) seconds);  /* set the alarm clock */
  1208.     if (setjmp(env) == 0) { /* if <> 0 then returned from timeout */
  1209.         if (read(0, &c, 1) < 0)  /* get a char; error means time out */
  1210.           {
  1211.              return(TIMEOUT);
  1212.           }
  1213.     }
  1214.     else return(TIMEOUT);
  1215.     alarm((unsigned) 0);  /* turn off the alarm */
  1216.     return((c&BITMASK));  /* return the char */
  1217. }
  1218.  
  1219. /* send a byte to data stream */
  1220. sendbyte(data)
  1221. char data;
  1222. {
  1223.     char dataout;
  1224.     dataout = (data&BITMASK);  /* mask for 7 or 8 bits */
  1225.     write(1, &dataout, 1);  /* write the byte */
  1226.     return;
  1227. }
  1228.  
  1229. /* function for alarm clock timeouts */
  1230. void alarmfunc()
  1231. {
  1232.     longjmp(env,1);  /* this is basically a dummy function to force error */
  1233.          /* status return on the "read" call in "readbyte"    */
  1234. }
  1235.  
  1236. /* print data on TTY setting */
  1237. ttyparams()
  1238. {
  1239.     
  1240. /*  Obtain TTY parameters for JHU UNIX  */
  1241. #ifdef JHU      
  1242.     gtty(0, &ttystemp);  /* get current tty params */
  1243. #endif
  1244.  
  1245. /*  Obtain TTY parameters for Version 7 UNIX  */
  1246. #ifdef VER7
  1247.     ioctl(0,TIOCGETP,&ttystemp);
  1248. #endif
  1249.  
  1250. /*  Obtain TTY parameters for UNIX SYSTEM III  */
  1251. #ifdef SYS3
  1252.     gtty(0, &ttystemp);  /* get current tty params */
  1253. #endif
  1254.  
  1255.     tty = ttyname(0);  /* get name of tty */
  1256.     stat(tty, &statbuf);  /* get more tty params */
  1257.  
  1258.     printf("\r\n\nTTY Device Parameter Display");
  1259.       printf("\r\n\tTTY Device Name is %s\r\n\n", tty);
  1260.       printf("\tAny Parity Allowed "); pryn(ANYP);
  1261.       printf("\tEven Parity Allowed"); pryn(EVENP);
  1262.       printf("\tOdd Parity Allowed "); pryn(ODDP);
  1263.       printf("\tEcho Enabled       "); pryn(ECHO);
  1264.       printf("\tLower Case Map     "); pryn(LCASE);
  1265.       printf("\tTabs Expanded      "); pryn(XTABS);
  1266.       printf("\tCR Mode Enabled    "); pryn(CRMOD);
  1267.       printf("\tRAW Mode Enabled   "); pryn(RAW);
  1268.  
  1269. /*  Print extended terminal characteristics for JHU UNIX  */
  1270. #ifdef JHU
  1271.       printf("\tBinary Mode Enabled"); pryn1(NB8);
  1272.       printf("\tCR/LF in Col 72    "); pryn1(FOLD);
  1273.       printf("\tRecognize ^S/^Q    "); pryn1(STALL);
  1274.       printf("\tSend ^S/^Q     "); pryn1(TAPE);
  1275.       printf("\tTerminal can BS    "); pryn1(SCOPE);
  1276.       printf("\r\n");  /* New line to separate topics */
  1277.       printf("\tTerminal Paging is "); pryn1(PAGE);
  1278.         if (ttystemp.xflags&PAGE)
  1279.         printf("\t  Lines/Page is %d\r\n", ttystemp.xflags&PAGE);
  1280.       printf("\r\n");  /* New line to separate topics */
  1281.       printf("\tTTY Input Rate     :   ");
  1282.         prbaud(ttystemp.ispeed);  /* print baud rate */
  1283.       printf("\tTTY Output Rate    :   ");
  1284.         prbaud(ttystemp.ospeed);  /* print output baud rate */
  1285.       printf("\r\n");  /* New line to separate topics */
  1286.       printf("\tMessages Enabled   ");
  1287.         if (statbuf.st_mode&011)
  1288.            printf(":   Yes\r\n");
  1289.         else
  1290.            printf(":   No\r\n");
  1291. #endif
  1292.  
  1293. /*  Print extended characteristics for Version 7 UNIX  */
  1294. #ifdef VER7
  1295.       printf("\tTTY Input Rate     :   ");
  1296.         prbaud(ttystemp.sg_ispeed);
  1297.       printf("\tTTY Output Rate    :   ");
  1298.         prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
  1299. #endif
  1300.  
  1301. /*  Print extended characteristics for UNIX SYSTEM III  */
  1302. #ifdef SYS3
  1303.       printf("\tTTY Input Rate     :   ");
  1304.         prbaud(ttystemp.sg_ispeed);
  1305.       printf("\tTTY Output Rate    :   ");
  1306.         prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
  1307. #endif
  1308.  
  1309. }
  1310.  
  1311. pryn(iflag)
  1312. int iflag;
  1313. {
  1314.  
  1315. /*  JHU UNIX flag test  */
  1316. #ifdef JHU
  1317.     if (ttystemp.mode&iflag)
  1318. #endif
  1319.  
  1320. /*  Version 7 UNIX flag test  */
  1321. #ifdef VER7
  1322.     if (ttystemp.sg_flags&iflag)
  1323. #endif
  1324.  
  1325. /*  UNIX SYSTEM III flag test  */
  1326. #ifdef SYS3
  1327.     if (ttystemp.sg_flags&iflag)
  1328. #endif
  1329.  
  1330.        printf(":   Yes\r\n");
  1331.     else
  1332.        printf(":   No\r\n");
  1333. }
  1334.  
  1335. /*  Extended flag test for JHU UNIX only  */
  1336. #ifdef JHU
  1337. pryn1(iflag)
  1338. int iflag;
  1339. {
  1340.     if (ttystemp.xflags&iflag)
  1341.        printf(":   Yes\r\n");
  1342.     else
  1343.        printf(":   No\r\n");
  1344. }
  1345. #endif
  1346.  
  1347. prbaud(speed)
  1348. char speed;
  1349. {
  1350.     switch (speed) {
  1351.  
  1352. /*  JHU UNIX speed flag cases  */
  1353. #ifdef JHU          
  1354.         case B0050 : printf("50"); break;
  1355.         case B0075 : printf("75"); break;
  1356.         case B0110 : printf("110"); break;
  1357.         case B0134 : printf("134.5"); break;
  1358.         case B0150 : printf("150"); break;
  1359.         case B0200 : printf("200"); break;
  1360.         case B0300 : printf("300"); break;
  1361.         case B0600 : printf("600"); break;
  1362.         case B1200 : printf("1200"); break;
  1363.         case B1800 : printf("1800"); break;
  1364.         case B2400 : printf("2400"); break;
  1365.         case B4800 : printf("4800"); break;
  1366.         case B9600 : printf("9600"); break;
  1367.         case EXT_A : printf("External A"); break;
  1368.         case EXT_B : printf("External B"); break;
  1369. #endif
  1370.  
  1371. /*  Version 7 UNIX speed flag cases  */
  1372. #ifdef VER7
  1373.         case B50 : printf("50"); break;
  1374.         case B75 : printf("75"); break;
  1375.         case B110 : printf("110"); break;
  1376.         case B134 : printf("134.5"); break;
  1377.         case B150 : printf("150"); break;
  1378.         case B200 : printf("200"); break;
  1379.         case B300 : printf("300"); break;
  1380.         case B600 : printf("600"); break;
  1381.         case B1200 : printf("1200"); break;
  1382.         case B1800 : printf("1800"); break;
  1383.         case B2400 : printf("2400"); break;
  1384.         case B4800 : printf("4800"); break;
  1385.         case B9600 : printf("9600"); break;
  1386.         case EXTA : printf("External A"); break;
  1387.         case EXTB : printf("External B"); break;
  1388. #endif
  1389.  
  1390. /*  UNIX SYSTEM III speed flag cases  */
  1391. #ifdef SYS3
  1392.         case B50 : printf("50"); break;
  1393.         case B75 : printf("75"); break;
  1394.         case B110 : printf("110"); break;
  1395.         case B134 : printf("134.5"); break;
  1396.         case B150 : printf("150"); break;
  1397.         case B200 : printf("200"); break;
  1398.         case B300 : printf("300"); break;
  1399.         case B600 : printf("600"); break;
  1400.         case B1200 : printf("1200"); break;
  1401.         case B1800 : printf("1800"); break;
  1402.         case B2400 : printf("2400"); break;
  1403.         case B4800 : printf("4800"); break;
  1404.         case B9600 : printf("9600"); break;
  1405.         c
  1406. /
  1407. #ifdef JHU
  1408. pryn1(iflag)
  1409. int iflag;
  1410. {
  1411.     if (ttystemp.xflags&iflag)
  1412.        printf(":   Yes\r\n");
  1413.     else
  1414.        printf(